feat(desktop, analytics): add packaging and usage export#172
feat(desktop, analytics): add packaging and usage export#172awsl233777 wants to merge 32 commits into
Conversation
|
Note Reviews pausedIt looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the Use the following commands to manage reviews:
Use the checkboxes below for quick actions:
📝 WalkthroughWalkthroughAdds a Tauri desktop shell for Codex Mate with staging, backend startup/shutdown logic, desktop build and release workflow updates, installer hooks, docs, and validation tests. ChangesDesktop Application with Tauri
Sequence Diagram(s)sequenceDiagram
participant Developer
participant StageScript as tools/desktop/prepare-tauri-resources.js
participant DesktopBuild as .github/workflows/desktop-build.yml
participant ReleaseWorkflow as .github/workflows/release.yml
participant TauriRuntime as src-tauri/src/main.rs + lib.rs
Developer->>StageScript: npm run desktop:stage
StageScript->>StageScript: copy runtime entries, node_modules, node-runtime
DesktopBuild->>DesktopBuild: build and verify Windows manifest
DesktopBuild->>DesktopBuild: upload desktop artifacts
ReleaseWorkflow->>ReleaseWorkflow: resolve, download artifacts, publish installers
TauriRuntime->>TauriRuntime: init_desktop_diagnostics() and run()
Estimated code review effort🎯 4 (Complex) | ⏱️ ~75 minutes Suggested reviewers
Poem
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
|
Updated this PR after rebasing onto latest Validation run locally:
@coderabbitai review |
|
✅ Actions performedFull review triggered. |
There was a problem hiding this comment.
Actionable comments posted: 5
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In @.github/workflows/desktop-build.yml:
- Around line 34-35: Replace floating action refs with pinned commit SHAs for
every `uses:` entry (e.g., change `actions/checkout@v4` to the corresponding
full commit SHA ref) and for the checkout step(s) add `persist-credentials:
false` under the step config to disable token persistence; update all
occurrences noted (the Checkout step and the other actions referenced) so each
`uses:` is a full commit SHA and each checkout step includes
`persist-credentials: false`.
In `@src-tauri/src/lib.rs`:
- Around line 116-124: The spawned child process from command.spawn() is not
terminated if wait_for_backend(Duration::from_secs(15)) returns false; modify
the error path so that when wait_for_backend(...) is false you call child.kill()
(and optionally child.wait() to reap it), handle/ignore any kill/wait errors,
and then return the Err string instead of leaving the process running; update
the block where you create let child = command.spawn() and the subsequent
readiness check to ensure child is killed and awaited before returning Err.
- Around line 39-44: The readiness probe currently only checks for "HTTP/1.1
200" or "HTTP/1.0 200" in the raw response (using response and
stream.read_to_string), which can false-positive for other services; update the
check so after reading the response it also validates a backend-specific
identity token (for example a unique header like "X-Backend: MyAppBackend" or a
distinct body string such as "MyAppBackend ready") in the response before
returning true; modify the conditional that currently returns
response.starts_with(...) to require both the 200 status line and the presence
of that unique identifier, and keep the existing error handling for
stream.read_to_string failures.
In `@tests/unit/desktop-stage.test.mjs`:
- Around line 54-56: The test currently uses a brittle full-object equality on
tauriConfig.bundle.resources via assert.deepStrictEqual; instead assert only
that the required mapping exists by checking that tauriConfig.bundle.resources
has the key '../dist/desktop/codexmate' and its value equals 'codexmate' (e.g.,
use hasOwnProperty or in-check plus assert.strictEqual on
tauriConfig.bundle.resources['../dist/desktop/codexmate']). Update the assertion
in tests/unit/desktop-stage.test.mjs to verify the single mapping rather than
the entire resources object.
In `@tools/desktop/prepare-tauri-resources.js`:
- Around line 48-53: The use of fs.cpSync in prepare-tauri-resources.js is
incompatible with engines.node >=14; either update package.json.engines to a
Node version that includes fs.cpSync or replace the fs.cpSync call with a
Node-14-compatible recursive copy routine: implement a small utility in
prepare-tauri-resources.js (e.g., copyDirRecursive) that creates destination
dirs with fs.mkdirSync(..., { recursive: true }), iterates entries with
fs.readdirSync, skips any path containing '.git' (match the existing filter
logic), copies files with fs.copyFileSync and handles directories recursively,
and preserves the intended dereference/force semantics as best-effort; modify
the code to call this utility instead of fs.cpSync (or bump engines.node if you
prefer the simpler change).
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: 95d40a9b-5e65-40b6-bcd5-49df9fc4fc2a
⛔ Files ignored due to path filters (16)
package-lock.jsonis excluded by!**/package-lock.jsonsrc-tauri/icons/128x128.pngis excluded by!**/*.pngsrc-tauri/icons/128x128@2x.pngis excluded by!**/*.pngsrc-tauri/icons/32x32.pngis excluded by!**/*.pngsrc-tauri/icons/Square107x107Logo.pngis excluded by!**/*.pngsrc-tauri/icons/Square142x142Logo.pngis excluded by!**/*.pngsrc-tauri/icons/Square150x150Logo.pngis excluded by!**/*.pngsrc-tauri/icons/Square284x284Logo.pngis excluded by!**/*.pngsrc-tauri/icons/Square30x30Logo.pngis excluded by!**/*.pngsrc-tauri/icons/Square310x310Logo.pngis excluded by!**/*.pngsrc-tauri/icons/Square44x44Logo.pngis excluded by!**/*.pngsrc-tauri/icons/Square71x71Logo.pngis excluded by!**/*.pngsrc-tauri/icons/Square89x89Logo.pngis excluded by!**/*.pngsrc-tauri/icons/StoreLogo.pngis excluded by!**/*.pngsrc-tauri/icons/icon.icois excluded by!**/*.icosrc-tauri/icons/icon.pngis excluded by!**/*.png
📒 Files selected for processing (15)
.github/workflows/desktop-build.ymldoc/desktop.mdpackage.jsonsrc-tauri/.gitignoresrc-tauri/Cargo.tomlsrc-tauri/build.rssrc-tauri/capabilities/default.jsonsrc-tauri/icons/icon.icnssrc-tauri/src/lib.rssrc-tauri/src/main.rssrc-tauri/tauri.conf.jsontests/unit/desktop-stage.test.mjstests/unit/npm-package-files.test.mjstests/unit/run.mjstools/desktop/prepare-tauri-resources.js
📜 Review details
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
- GitHub Check: Windows
- GitHub Check: macOS
🧰 Additional context used
🪛 zizmor (1.25.2)
.github/workflows/desktop-build.yml
[warning] 34-35: credential persistence through GitHub Actions artifacts (artipacked): does not set persist-credentials: false
(artipacked)
[error] 35-35: unpinned action reference (unpinned-uses): action is not pinned to a hash (required by blanket policy)
(unpinned-uses)
[error] 38-38: unpinned action reference (unpinned-uses): action is not pinned to a hash (required by blanket policy)
(unpinned-uses)
[error] 44-44: unpinned action reference (unpinned-uses): action is not pinned to a hash (required by blanket policy)
(unpinned-uses)
[error] 59-59: unpinned action reference (unpinned-uses): action is not pinned to a hash (required by blanket policy)
(unpinned-uses)
🔇 Additional comments (10)
doc/desktop.md (1)
1-62: LGTM!src-tauri/.gitignore (1)
1-4: LGTM!src-tauri/Cargo.toml (1)
1-25: LGTM!src-tauri/build.rs (1)
1-3: LGTM!src-tauri/capabilities/default.json (1)
1-11: LGTM!src-tauri/tauri.conf.json (1)
1-47: LGTM!src-tauri/src/main.rs (1)
1-6: LGTM!package.json (1)
45-49: LGTM!Also applies to: 79-80
tests/unit/npm-package-files.test.mjs (1)
20-25: LGTM!tests/unit/run.mjs (1)
57-57: LGTM!
There was a problem hiding this comment.
Actionable comments posted: 1
♻️ Duplicate comments (5)
tests/unit/desktop-stage.test.mjs (1)
54-56:⚠️ Potential issue | 🟡 Minor | ⚡ Quick winAvoid brittle full-object equality for
bundle.resources.Assert the required mapping instead of the whole object so valid extra resources don’t break this test.
Proposed fix
- assert.deepStrictEqual(tauriConfig.bundle.resources, { - '../dist/desktop/codexmate': 'codexmate' - }); + assert.strictEqual( + tauriConfig.bundle?.resources?.['../dist/desktop/codexmate'], + 'codexmate', + 'tauri bundle.resources must map ../dist/desktop/codexmate to codexmate' + );🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@tests/unit/desktop-stage.test.mjs` around lines 54 - 56, The test currently asserts full-object equality on tauriConfig.bundle.resources which is brittle; update the assertion in tests/unit/desktop-stage.test.mjs to check only that the required mapping exists (e.g., assert that tauriConfig.bundle.resources['../dist/desktop/codexmate'] equals 'codexmate' or that Object.prototype.hasOwnProperty.call(tauriConfig.bundle.resources, '../dist/desktop/codexmate') and its value is 'codexmate') so extra resources won’t break the test while still verifying the necessary mapping.tools/desktop/prepare-tauri-resources.js (1)
48-53:⚠️ Potential issue | 🟠 Major | ⚡ Quick winAlign declared Node support with
fs.cpSyncusage.
fs.cpSynchere breaks on Node 14, but the project still declaresengines.node >=14. Please either raise the engine floor (e.g. Node >=16.7) or replace this copy path with a Node-14-compatible recursive implementation.#!/bin/bash set -euo pipefail echo "Declared Node engine in package.json:" rg -n '"engines"\s*:\s*\{|"node"\s*:' package.json -A2 -B1 echo echo "Node API usage in desktop staging script:" rg -n '\bfs\.cpSync\b' tools/desktop/prepare-tauri-resources.js -C2🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@tools/desktop/prepare-tauri-resources.js` around lines 48 - 53, The code uses fs.cpSync in prepare-tauri-resources.js which requires a newer Node than the project's declared engines.node (>=14); either update package.json engines.node to a minimum Node version that supports fs.cpSync (e.g., ">=16.7.0") or replace the fs.cpSync call with a Node-14-compatible recursive copier: implement a copyDirSync function (using fs.readdirSync, fs.statSync/lstatSync to honor dereference, fs.mkdirSync, fs.copyFileSync and handling overwrite/force) and apply the same filter logic (skip paths containing '.git') before calling it in place of fs.cpSync; ensure the replacement preserves recursive, force/overwrite, dereference, and filter behavior used in the original fs.cpSync invocation..github/workflows/desktop-build.yml (1)
34-35:⚠️ Potential issue | 🟠 Major | ⚡ Quick winPin all workflow actions to commit SHAs and harden checkout credentials.
This workflow still uses floating action refs and keeps default checkout credential persistence. Pin every
uses:to full commit SHAs and setpersist-credentials: falseon checkout.#!/bin/bash set -euo pipefail echo "Unpinned action refs:" rg -n '^\s*uses:\s*[^@]+@(v[0-9]+|stable|main|master)\s*$' .github/workflows/desktop-build.yml echo echo "Checkout credential persistence setting:" rg -n '^\s*- name:\s*Checkout|persist-credentials' .github/workflows/desktop-build.yml -C2Also applies to: 38-38, 44-44, 59-59
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In @.github/workflows/desktop-build.yml around lines 34 - 35, Pin every "uses:" entry to a full commit SHA instead of floating refs (e.g., replace uses: actions/checkout@v4 with the corresponding commit SHA for actions/checkout and do the same for any other uses: entries currently pinned to tags/branches), and harden the Checkout step by adding persist-credentials: false under the step that contains uses: actions/checkout@... (ensure the key is present and set to false). Locate these changes by searching for the literal "uses: actions/checkout@" and other "uses:" entries in the workflow and update each to its full commit SHA; add or update the "persist-credentials" field in the checkout step to false so credentials are not persisted.src-tauri/src/lib.rs (2)
116-124:⚠️ Potential issue | 🟠 Major | ⚡ Quick winKill the spawned backend if readiness times out.
If
wait_for_backend()times out, the function returns an error without terminating the already-spawned child process, leaving an orphaned backend running.🧹 Proposed fix to clean up on timeout
- let child = command + let mut child = command .spawn() .map_err(|err| format!("unable to start codexmate backend with Node.js: {err}"))?; if !wait_for_backend(Duration::from_secs(15)) { + let _ = child.kill(); + let _ = child.wait(); return Err("codexmate backend did not become ready on 127.0.0.1:3737".into()); } Ok(Some(child))🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src-tauri/src/lib.rs` around lines 116 - 124, After spawning the child with command.spawn() and before returning an error when wait_for_backend(Duration::from_secs(15)) returns false, ensure you terminate the spawned process: call child.kill() (handle/ignore errors if the process already exited) and then call child.wait() to reap it; only after killing/waiting return the error string. This guarantees the spawned child (variable child from command.spawn()) is cleaned up on wait_for_backend timeout.
39-44:⚠️ Potential issue | 🟠 Major | ⚡ Quick winMake the readiness probe validate backend identity, not just status code.
The current health check only verifies HTTP 200 status, which could false-positive if an unrelated service is running on
127.0.0.1:3737, causing the app to skip backend startup or connect to the wrong service.🔍 Proposed fix to validate backend identity
let mut response = String::new(); if stream.read_to_string(&mut response).is_err() { return false; } - response.starts_with("HTTP/1.1 200") || response.starts_with("HTTP/1.0 200") + (response.starts_with("HTTP/1.1 200") || response.starts_with("HTTP/1.0 200")) + && response.contains("\"ok\":true")This checks for a backend-specific token in the response body to confirm identity.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src-tauri/src/lib.rs` around lines 39 - 44, The readiness probe currently only checks the HTTP status by calling stream.read_to_string(&mut response) and response.starts_with("HTTP/1.1 200") || response.starts_with("HTTP/1.0 200"); update this logic to also validate a backend-specific identity token in the response body (e.g., a known marker like "X-BACKEND-ID: my-backend" or "MY_BACKEND_READY") before returning true, so after successful read_to_string verify both the 200 status and response.contains("<IDENTITY_TOKEN>") and return false if the token is missing.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@src-tauri/tauri.conf.json`:
- Around line 26-28: Replace the null Content Security Policy in tauri.conf.json
by setting the security.csp key to a restrictive CSP string that permits only
'self' and the local backend origin (http://127.0.0.1:3737) and only the minimal
additional directives your frontend needs (e.g., avoid unsafe-eval, avoid
unsafe-inline unless absolutely required); update the security.csp value (the
"security": {"csp": ...} entry) accordingly so CSP is enforced rather than
disabled.
---
Duplicate comments:
In @.github/workflows/desktop-build.yml:
- Around line 34-35: Pin every "uses:" entry to a full commit SHA instead of
floating refs (e.g., replace uses: actions/checkout@v4 with the corresponding
commit SHA for actions/checkout and do the same for any other uses: entries
currently pinned to tags/branches), and harden the Checkout step by adding
persist-credentials: false under the step that contains uses:
actions/checkout@... (ensure the key is present and set to false). Locate these
changes by searching for the literal "uses: actions/checkout@" and other "uses:"
entries in the workflow and update each to its full commit SHA; add or update
the "persist-credentials" field in the checkout step to false so credentials are
not persisted.
In `@src-tauri/src/lib.rs`:
- Around line 116-124: After spawning the child with command.spawn() and before
returning an error when wait_for_backend(Duration::from_secs(15)) returns false,
ensure you terminate the spawned process: call child.kill() (handle/ignore
errors if the process already exited) and then call child.wait() to reap it;
only after killing/waiting return the error string. This guarantees the spawned
child (variable child from command.spawn()) is cleaned up on wait_for_backend
timeout.
- Around line 39-44: The readiness probe currently only checks the HTTP status
by calling stream.read_to_string(&mut response) and
response.starts_with("HTTP/1.1 200") || response.starts_with("HTTP/1.0 200");
update this logic to also validate a backend-specific identity token in the
response body (e.g., a known marker like "X-BACKEND-ID: my-backend" or
"MY_BACKEND_READY") before returning true, so after successful read_to_string
verify both the 200 status and response.contains("<IDENTITY_TOKEN>") and return
false if the token is missing.
In `@tests/unit/desktop-stage.test.mjs`:
- Around line 54-56: The test currently asserts full-object equality on
tauriConfig.bundle.resources which is brittle; update the assertion in
tests/unit/desktop-stage.test.mjs to check only that the required mapping exists
(e.g., assert that tauriConfig.bundle.resources['../dist/desktop/codexmate']
equals 'codexmate' or that
Object.prototype.hasOwnProperty.call(tauriConfig.bundle.resources,
'../dist/desktop/codexmate') and its value is 'codexmate') so extra resources
won’t break the test while still verifying the necessary mapping.
In `@tools/desktop/prepare-tauri-resources.js`:
- Around line 48-53: The code uses fs.cpSync in prepare-tauri-resources.js which
requires a newer Node than the project's declared engines.node (>=14); either
update package.json engines.node to a minimum Node version that supports
fs.cpSync (e.g., ">=16.7.0") or replace the fs.cpSync call with a
Node-14-compatible recursive copier: implement a copyDirSync function (using
fs.readdirSync, fs.statSync/lstatSync to honor dereference, fs.mkdirSync,
fs.copyFileSync and handling overwrite/force) and apply the same filter logic
(skip paths containing '.git') before calling it in place of fs.cpSync; ensure
the replacement preserves recursive, force/overwrite, dereference, and filter
behavior used in the original fs.cpSync invocation.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: e089cd15-bd97-4c65-8b49-bc57bab0cb3b
⛔ Files ignored due to path filters (16)
package-lock.jsonis excluded by!**/package-lock.jsonsrc-tauri/icons/128x128.pngis excluded by!**/*.pngsrc-tauri/icons/128x128@2x.pngis excluded by!**/*.pngsrc-tauri/icons/32x32.pngis excluded by!**/*.pngsrc-tauri/icons/Square107x107Logo.pngis excluded by!**/*.pngsrc-tauri/icons/Square142x142Logo.pngis excluded by!**/*.pngsrc-tauri/icons/Square150x150Logo.pngis excluded by!**/*.pngsrc-tauri/icons/Square284x284Logo.pngis excluded by!**/*.pngsrc-tauri/icons/Square30x30Logo.pngis excluded by!**/*.pngsrc-tauri/icons/Square310x310Logo.pngis excluded by!**/*.pngsrc-tauri/icons/Square44x44Logo.pngis excluded by!**/*.pngsrc-tauri/icons/Square71x71Logo.pngis excluded by!**/*.pngsrc-tauri/icons/Square89x89Logo.pngis excluded by!**/*.pngsrc-tauri/icons/StoreLogo.pngis excluded by!**/*.pngsrc-tauri/icons/icon.icois excluded by!**/*.icosrc-tauri/icons/icon.pngis excluded by!**/*.png
📒 Files selected for processing (15)
.github/workflows/desktop-build.ymldoc/desktop.mdpackage.jsonsrc-tauri/.gitignoresrc-tauri/Cargo.tomlsrc-tauri/build.rssrc-tauri/capabilities/default.jsonsrc-tauri/icons/icon.icnssrc-tauri/src/lib.rssrc-tauri/src/main.rssrc-tauri/tauri.conf.jsontests/unit/desktop-stage.test.mjstests/unit/npm-package-files.test.mjstests/unit/run.mjstools/desktop/prepare-tauri-resources.js
📜 Review details
🧰 Additional context used
🪛 zizmor (1.25.2)
.github/workflows/desktop-build.yml
[warning] 34-35: credential persistence through GitHub Actions artifacts (artipacked): does not set persist-credentials: false
(artipacked)
[error] 35-35: unpinned action reference (unpinned-uses): action is not pinned to a hash (required by blanket policy)
(unpinned-uses)
[error] 38-38: unpinned action reference (unpinned-uses): action is not pinned to a hash (required by blanket policy)
(unpinned-uses)
[error] 44-44: unpinned action reference (unpinned-uses): action is not pinned to a hash (required by blanket policy)
(unpinned-uses)
[error] 59-59: unpinned action reference (unpinned-uses): action is not pinned to a hash (required by blanket policy)
(unpinned-uses)
🔇 Additional comments (11)
doc/desktop.md (1)
1-61: LGTM!package.json (1)
45-49: LGTM!Also applies to: 79-80
tests/unit/npm-package-files.test.mjs (1)
20-25: LGTM!tests/unit/run.mjs (1)
57-57: LGTM!src-tauri/.gitignore (1)
1-4: LGTM!src-tauri/build.rs (1)
1-3: LGTM!src-tauri/capabilities/default.json (1)
1-11: LGTM!src-tauri/src/lib.rs (2)
146-158: LGTM!
160-164: LGTM!src-tauri/src/main.rs (1)
1-6: LGTM!src-tauri/Cargo.toml (1)
3-3: ⚡ Quick winCheck
src-tauri/Cargo.tomlfor current/secure Rust + Tauri pins
- crates.io latest:
tauri2.11.2,tauri-build2.6.2,tauri-plugin-log2.8.0.- Security advisory affects
tauriversions>= 2.0.0, <= 2.11.0(patched in2.11.1), so the pinnedtauriversion must be>= 2.11.1.- The provided snippet only shows
version = "0.0.36"; confirm the actualtauri*dependency versions and[package].rust-versioninsrc-tauri/Cargo.tomland update if they fall into vulnerable/outdated ranges (Rust stable is currently 1.95.0).
|
Updated the desktop app icons from Validation run locally:
Notes:
@coderabbitai re-review |
|
✅ Actions performedFull review triggered. |
There was a problem hiding this comment.
Actionable comments posted: 1
♻️ Duplicate comments (5)
.github/workflows/desktop-build.yml (1)
34-35:⚠️ Potential issue | 🟠 Major | ⚡ Quick winHarden workflow actions by pinning SHAs and disabling checkout credential persistence.
The workflow still uses floating action refs and keeps default checkout credential persistence. Pin each
uses:to a full commit SHA and setpersist-credentials: falsein the checkout step.#!/bin/bash set -euo pipefail echo "All action references:" rg -n '^\s*uses:\s*' .github/workflows/desktop-build.yml echo echo "Checkout credential persistence setting:" rg -n 'persist-credentials' .github/workflows/desktop-build.yml || trueAlso applies to: 38-38, 44-44, 59-59
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In @.github/workflows/desktop-build.yml around lines 34 - 35, Replace floating action refs and enable non-persistent checkout credentials: pin every "uses:" action to a full commit SHA instead of tags (e.g., replace uses: actions/checkout@v4 with a specific commit SHA) and add persist-credentials: false to the checkout step; apply these changes for the checkout occurrences and any other "uses:" lines referenced in the file so all actions are SHA-pinned and the Checkout step sets persist-credentials: false.tools/desktop/prepare-tauri-resources.js (1)
48-53:⚠️ Potential issue | 🟠 Major | ⚡ Quick winAlign runtime floor with
fs.cpSyncusage.
fs.cpSyncat Line 48 is incompatible with the declarednode >=14support, sodesktop:stagecan fail on supported runtimes. Either raise the engine floor for desktop-supporting environments or replace this with a Node-14-compatible recursive copy path.#!/bin/bash set -euo pipefail echo "Declared Node engine:" rg -n '"engines"\s*:\s*\{|"node"\s*:' package.json -n -A2 -B1 echo echo "Node APIs used by desktop staging script:" rg -n '\bfs\.cpSync\b|\bfs\.rmSync\b' tools/desktop/prepare-tauri-resources.js -C2🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@tools/desktop/prepare-tauri-resources.js` around lines 48 - 53, The script prepare-tauri-resources.js currently calls fs.cpSync (symbol: fs.cpSync) which is only available in Node >=16 and thus conflicts with the declared node >=14 engine; either raise the project's Node engine to a version that supports fs.cpSync or replace this call with a Node-14-compatible implementation (e.g., use fs-extra.copySync or implement a recursive copy helper and use fs.readdir/fs.copyFile/fs.mkdir) and preserve the existing options (recursive, force, dereference, filter logic that excludes '.git'); update any imports/require usage accordingly and ensure prepare-tauri-resources.js continues to exclude .git paths as before.src-tauri/src/lib.rs (2)
116-122:⚠️ Potential issue | 🟠 Major | ⚡ Quick winTerminate the spawned backend when readiness times out.
Lines 116–121 return an error without killing/reaping the child process, leaving a stray backend process running.
🛠️ Suggested fix
- let child = command + let mut child = command .spawn() .map_err(|err| format!("unable to start codexmate backend with Node.js: {err}"))?; if !wait_for_backend(Duration::from_secs(15)) { + let _ = child.kill(); + let _ = child.wait(); return Err("codexmate backend did not become ready on 127.0.0.1:3737".into()); }🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src-tauri/src/lib.rs` around lines 116 - 122, The code spawns a child process into the variable child but returns early when wait_for_backend(Duration::from_secs(15)) is false without killing or reaping that child; update the timeout branch to terminate and reap the process: call child.kill() (handle/ignore any kill error) and then child.wait() (or wait_with_output/try_wait) before returning the Err so the spawned backend is not left running; keep references to the child variable and add minimal error handling/logging around kill() and wait() in the same scope where wait_for_backend is checked.
39-44:⚠️ Potential issue | 🟠 Major | ⚡ Quick winMake readiness verification backend-specific, not status-only.
Line 43 treats any local HTTP 200 as healthy, which can false-positive against an unrelated service on
127.0.0.1:3737.✅ Suggested fix
- response.starts_with("HTTP/1.1 200") || response.starts_with("HTTP/1.0 200") + let status_ok = response.starts_with("HTTP/1.1 200") || response.starts_with("HTTP/1.0 200"); + let identity_ok = response.contains("\"ok\":true"); + status_ok && identity_ok🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src-tauri/src/lib.rs` around lines 39 - 44, The current readiness check only inspects the HTTP status line using response.starts_with(...) which can false-positive against any service on 127.0.0.1:3737; update the readiness logic (the block that calls stream.read_to_string(&mut response) and currently returns based on response.starts_with("HTTP/1.1 200") || response.starts_with("HTTP/1.0 200")) to validate a backend-specific signature instead: parse the HTTP response and verify both the 200 status and a unique marker (e.g., a specific response path/body JSON field or header such as an X-Backend or a known body token) that your backend exposes so only the intended service is considered healthy. Ensure you still handle read errors from stream.read_to_string and return false on failure, but replace the bare status-line check with a combined status + backend-identifier check using the response string you already populate.src-tauri/tauri.conf.json (1)
26-28:⚠️ Potential issue | 🟠 Major | ⚡ Quick winEnable a restrictive CSP instead of disabling it.
Line 27 sets CSP to
null, which removes webview-side injection protections even for localhost content.🔒 Suggested fix
"security": { - "csp": null + "csp": "default-src 'self' http://127.0.0.1:3737; connect-src 'self' http://127.0.0.1:3737; img-src 'self' data:; style-src 'self' 'unsafe-inline'; script-src 'self'" }🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src-tauri/tauri.conf.json` around lines 26 - 28, The CSP is currently disabled by setting the "csp" key to null inside the "security" object; replace that with a restrictive Content Security Policy string (rather than null) to re-enable webview-side protections—update the "security"."csp" value to a restrictive policy that limits sources to self and local dev endpoints (for example, a policy restricting default-src to 'self' and localhost, limiting script-src/style-src/connect-src to 'self' and localhost, and allowing images from 'self' and data:); ensure the "csp" key contains that policy string so the tauri webview enforces it instead of being disabled.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@src-tauri/src/lib.rs`:
- Around line 74-76: Remove the unsafe production fallback that adds
current_dir.join("cli.js") to candidates; instead only allow this behavior in
non-production (debug) builds. Locate the block that pushes
current_dir.join("cli.js") into the candidates vector (the current_dir / cli.js
fallback) and wrap it behind a debug-only guard (e.g., cfg!(debug_assertions))
so that in release builds the current working directory is not used as a
resource lookup candidate.
---
Duplicate comments:
In @.github/workflows/desktop-build.yml:
- Around line 34-35: Replace floating action refs and enable non-persistent
checkout credentials: pin every "uses:" action to a full commit SHA instead of
tags (e.g., replace uses: actions/checkout@v4 with a specific commit SHA) and
add persist-credentials: false to the checkout step; apply these changes for the
checkout occurrences and any other "uses:" lines referenced in the file so all
actions are SHA-pinned and the Checkout step sets persist-credentials: false.
In `@src-tauri/src/lib.rs`:
- Around line 116-122: The code spawns a child process into the variable child
but returns early when wait_for_backend(Duration::from_secs(15)) is false
without killing or reaping that child; update the timeout branch to terminate
and reap the process: call child.kill() (handle/ignore any kill error) and then
child.wait() (or wait_with_output/try_wait) before returning the Err so the
spawned backend is not left running; keep references to the child variable and
add minimal error handling/logging around kill() and wait() in the same scope
where wait_for_backend is checked.
- Around line 39-44: The current readiness check only inspects the HTTP status
line using response.starts_with(...) which can false-positive against any
service on 127.0.0.1:3737; update the readiness logic (the block that calls
stream.read_to_string(&mut response) and currently returns based on
response.starts_with("HTTP/1.1 200") || response.starts_with("HTTP/1.0 200")) to
validate a backend-specific signature instead: parse the HTTP response and
verify both the 200 status and a unique marker (e.g., a specific response
path/body JSON field or header such as an X-Backend or a known body token) that
your backend exposes so only the intended service is considered healthy. Ensure
you still handle read errors from stream.read_to_string and return false on
failure, but replace the bare status-line check with a combined status +
backend-identifier check using the response string you already populate.
In `@src-tauri/tauri.conf.json`:
- Around line 26-28: The CSP is currently disabled by setting the "csp" key to
null inside the "security" object; replace that with a restrictive Content
Security Policy string (rather than null) to re-enable webview-side
protections—update the "security"."csp" value to a restrictive policy that
limits sources to self and local dev endpoints (for example, a policy
restricting default-src to 'self' and localhost, limiting
script-src/style-src/connect-src to 'self' and localhost, and allowing images
from 'self' and data:); ensure the "csp" key contains that policy string so the
tauri webview enforces it instead of being disabled.
In `@tools/desktop/prepare-tauri-resources.js`:
- Around line 48-53: The script prepare-tauri-resources.js currently calls
fs.cpSync (symbol: fs.cpSync) which is only available in Node >=16 and thus
conflicts with the declared node >=14 engine; either raise the project's Node
engine to a version that supports fs.cpSync or replace this call with a
Node-14-compatible implementation (e.g., use fs-extra.copySync or implement a
recursive copy helper and use fs.readdir/fs.copyFile/fs.mkdir) and preserve the
existing options (recursive, force, dereference, filter logic that excludes
'.git'); update any imports/require usage accordingly and ensure
prepare-tauri-resources.js continues to exclude .git paths as before.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: 20600851-56c4-4332-9661-57ed83462160
⛔ Files ignored due to path filters (54)
package-lock.jsonis excluded by!**/package-lock.jsonsite/.vitepress/public/images/logo-v.pngis excluded by!**/*.pngsite/.vitepress/public/images/logo.pngis excluded by!**/*.pngsite/.vitepress/public/images/logo.svgis excluded by!**/*.svgsite/.vitepress/public/images/web-ui-screenshot.pngis excluded by!**/*.pngsrc-tauri/icons/128x128.pngis excluded by!**/*.pngsrc-tauri/icons/128x128@2x.pngis excluded by!**/*.pngsrc-tauri/icons/32x32.pngis excluded by!**/*.pngsrc-tauri/icons/64x64.pngis excluded by!**/*.pngsrc-tauri/icons/Square107x107Logo.pngis excluded by!**/*.pngsrc-tauri/icons/Square142x142Logo.pngis excluded by!**/*.pngsrc-tauri/icons/Square150x150Logo.pngis excluded by!**/*.pngsrc-tauri/icons/Square284x284Logo.pngis excluded by!**/*.pngsrc-tauri/icons/Square30x30Logo.pngis excluded by!**/*.pngsrc-tauri/icons/Square310x310Logo.pngis excluded by!**/*.pngsrc-tauri/icons/Square44x44Logo.pngis excluded by!**/*.pngsrc-tauri/icons/Square71x71Logo.pngis excluded by!**/*.pngsrc-tauri/icons/Square89x89Logo.pngis excluded by!**/*.pngsrc-tauri/icons/StoreLogo.pngis excluded by!**/*.pngsrc-tauri/icons/android/mipmap-hdpi/ic_launcher.pngis excluded by!**/*.pngsrc-tauri/icons/android/mipmap-hdpi/ic_launcher_foreground.pngis excluded by!**/*.pngsrc-tauri/icons/android/mipmap-hdpi/ic_launcher_round.pngis excluded by!**/*.pngsrc-tauri/icons/android/mipmap-mdpi/ic_launcher.pngis excluded by!**/*.pngsrc-tauri/icons/android/mipmap-mdpi/ic_launcher_foreground.pngis excluded by!**/*.pngsrc-tauri/icons/android/mipmap-mdpi/ic_launcher_round.pngis excluded by!**/*.pngsrc-tauri/icons/android/mipmap-xhdpi/ic_launcher.pngis excluded by!**/*.pngsrc-tauri/icons/android/mipmap-xhdpi/ic_launcher_foreground.pngis excluded by!**/*.pngsrc-tauri/icons/android/mipmap-xhdpi/ic_launcher_round.pngis excluded by!**/*.pngsrc-tauri/icons/android/mipmap-xxhdpi/ic_launcher.pngis excluded by!**/*.pngsrc-tauri/icons/android/mipmap-xxhdpi/ic_launcher_foreground.pngis excluded by!**/*.pngsrc-tauri/icons/android/mipmap-xxhdpi/ic_launcher_round.pngis excluded by!**/*.pngsrc-tauri/icons/android/mipmap-xxxhdpi/ic_launcher.pngis excluded by!**/*.pngsrc-tauri/icons/android/mipmap-xxxhdpi/ic_launcher_foreground.pngis excluded by!**/*.pngsrc-tauri/icons/android/mipmap-xxxhdpi/ic_launcher_round.pngis excluded by!**/*.pngsrc-tauri/icons/icon.icois excluded by!**/*.icosrc-tauri/icons/icon.pngis excluded by!**/*.pngsrc-tauri/icons/ios/AppIcon-20x20@1x.pngis excluded by!**/*.pngsrc-tauri/icons/ios/AppIcon-20x20@2x-1.pngis excluded by!**/*.pngsrc-tauri/icons/ios/AppIcon-20x20@2x.pngis excluded by!**/*.pngsrc-tauri/icons/ios/AppIcon-20x20@3x.pngis excluded by!**/*.pngsrc-tauri/icons/ios/AppIcon-29x29@1x.pngis excluded by!**/*.pngsrc-tauri/icons/ios/AppIcon-29x29@2x-1.pngis excluded by!**/*.pngsrc-tauri/icons/ios/AppIcon-29x29@2x.pngis excluded by!**/*.pngsrc-tauri/icons/ios/AppIcon-29x29@3x.pngis excluded by!**/*.pngsrc-tauri/icons/ios/AppIcon-40x40@1x.pngis excluded by!**/*.pngsrc-tauri/icons/ios/AppIcon-40x40@2x-1.pngis excluded by!**/*.pngsrc-tauri/icons/ios/AppIcon-40x40@2x.pngis excluded by!**/*.pngsrc-tauri/icons/ios/AppIcon-40x40@3x.pngis excluded by!**/*.pngsrc-tauri/icons/ios/AppIcon-512@2x.pngis excluded by!**/*.pngsrc-tauri/icons/ios/AppIcon-60x60@2x.pngis excluded by!**/*.pngsrc-tauri/icons/ios/AppIcon-60x60@3x.pngis excluded by!**/*.pngsrc-tauri/icons/ios/AppIcon-76x76@1x.pngis excluded by!**/*.pngsrc-tauri/icons/ios/AppIcon-76x76@2x.pngis excluded by!**/*.pngsrc-tauri/icons/ios/AppIcon-83.5x83.5@2x.pngis excluded by!**/*.png
📒 Files selected for processing (17)
.github/workflows/desktop-build.ymldoc/desktop.mdpackage.jsonsrc-tauri/.gitignoresrc-tauri/Cargo.tomlsrc-tauri/build.rssrc-tauri/capabilities/default.jsonsrc-tauri/icons/android/mipmap-anydpi-v26/ic_launcher.xmlsrc-tauri/icons/android/values/ic_launcher_background.xmlsrc-tauri/icons/icon.icnssrc-tauri/src/lib.rssrc-tauri/src/main.rssrc-tauri/tauri.conf.jsontests/unit/desktop-stage.test.mjstests/unit/npm-package-files.test.mjstests/unit/run.mjstools/desktop/prepare-tauri-resources.js
📜 Review details
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
- GitHub Check: Windows
- GitHub Check: macOS
🧰 Additional context used
🪛 zizmor (1.25.2)
.github/workflows/desktop-build.yml
[warning] 34-35: credential persistence through GitHub Actions artifacts (artipacked): does not set persist-credentials: false
(artipacked)
[error] 35-35: unpinned action reference (unpinned-uses): action is not pinned to a hash (required by blanket policy)
(unpinned-uses)
[error] 38-38: unpinned action reference (unpinned-uses): action is not pinned to a hash (required by blanket policy)
(unpinned-uses)
[error] 44-44: unpinned action reference (unpinned-uses): action is not pinned to a hash (required by blanket policy)
(unpinned-uses)
[error] 59-59: unpinned action reference (unpinned-uses): action is not pinned to a hash (required by blanket policy)
(unpinned-uses)
🔇 Additional comments (13)
doc/desktop.md (1)
1-61: LGTM!tests/unit/desktop-stage.test.mjs (1)
54-56: ⚡ Quick winAssert only the required
bundle.resourcesmapping.This assertion is brittle because it enforces the entire object shape, not just the contract required by this PR.
Proposed fix
- assert.deepStrictEqual(tauriConfig.bundle.resources, { - '../dist/desktop/codexmate': 'codexmate' - }); + assert.strictEqual( + tauriConfig.bundle?.resources?.['../dist/desktop/codexmate'], + 'codexmate', + 'tauri bundle.resources must map ../dist/desktop/codexmate to codexmate' + );package.json (1)
45-49: LGTM!Also applies to: 79-80
tests/unit/npm-package-files.test.mjs (1)
20-25: LGTM!tests/unit/run.mjs (1)
57-57: LGTM!src-tauri/.gitignore (1)
1-4: LGTM!src-tauri/Cargo.toml (1)
1-25: LGTM!src-tauri/build.rs (1)
1-3: LGTM!src-tauri/capabilities/default.json (1)
1-11: LGTM!src-tauri/icons/android/mipmap-anydpi-v26/ic_launcher.xml (1)
1-5: LGTM!src-tauri/icons/android/values/ic_launcher_background.xml (1)
1-4: LGTM!src-tauri/src/main.rs (2)
1-2: LGTM!
4-6: ⚡ Quick winConfirm
app_libmatches the Tauri library crate andrun()is exported
src-tauri/Cargo.tomlsets[lib] name = "app_lib", matchingapp_lib::run()insrc-tauri/src/main.rs.src-tauri/src/lib.rsexportspub fn run().- While
run()returns(), it still handles failures via?in.setup(...)and.expect("error while running tauri application").
兔子审查 - 必须修复的问题🔴 Critical (安全/资源泄漏)1.
|
|
@coderabbitai re-review I addressed the findings from #172 (comment) in commit
Validation actually run: Local limitation: this environment does not have Could you please verify whether the previously listed issues are now resolved? |
🧩 Analysis chain🏁 Script executed: #!/bin/bash
echo "=== 1. .github/workflows/desktop-build.yml ==="
cat .github/workflows/desktop-build.yml
echo ""
echo "=== 2 & 3. src-tauri/src/lib.rs ==="
cat src-tauri/src/lib.rs
echo ""
echo "=== 4. src-tauri/tauri.conf.json ==="
cat src-tauri/tauri.conf.json
echo ""
echo "=== 5. package.json (engines) ==="
python3 -c "import json; d=json.load(open('package.json')); print('engines:', d.get('engines')); print('devDeps tauri:', d.get('devDependencies',{}).get('`@tauri-apps/cli`'))"
echo ""
echo "=== 6. tests/unit/desktop-stage.test.mjs ==="
cat tests/unit/desktop-stage.test.mjsLength of output: 10697
The only remaining item (Rust ✅ Actions performedFull review triggered. |
|
@coderabbitai re-review Follow-up on the remaining desktop review item:
Latest validation actually run after this change: The prior six items from #172 (comment) remain addressed, and CI on the previous head was green before this follow-up commit. Please verify whether the remaining review concern is now resolved on the latest head. |
|
Your plan includes 2 PR reviews per hour. More reviews will be available in 19 minutes and 40 seconds. |
|
@coderabbitai re-review Follow-up release packaging change in
Validation actually run: Please verify the latest head, especially the release workflow artifact handoff and release asset globs. |
🧩 Analysis chain🏁 Script executed: #!/bin/bash
echo "=== Release workflow ==="
fd -e yml -e yaml . .github/workflows/ --exec cat {}
echo ""
echo "=== Desktop build workflow ==="
cat .github/workflows/desktop-build.yml 2>/dev/null || echo "not found"
echo ""
echo "=== Unit test files (new contract test) ==="
fd 'release' tests/unit/ 2>/dev/null || fd '\.test\.mjs$' tests/unit/ | sort
echo ""
echo "=== tests/unit/run.mjs ==="
cat tests/unit/run.mjs
echo ""
echo "=== All test mjs files listing ==="
fd '\.test\.mjs$' tests/unit/ | sortLength of output: 25332 🏁 Script executed: #!/bin/bash
# Read any new release-related test files
echo "=== release workflow contract test (if any) ==="
fd 'release' tests/unit/ 2>/dev/null
fd 'release' tests/ 2>/dev/null
echo ""
echo "=== Newer test files ==="
ls -la tests/unit/
echo ""
echo "=== package.json scripts section ==="
python3 -c "import json; d=json.load(open('package.json')); [print(k,'=',v) for k,v in d.get('scripts',{}).items()]"
echo ""
echo "=== package.json engines ==="
python3 -c "import json; d=json.load(open('package.json')); print(d.get('engines'))"Length of output: 7351 🏁 Script executed: #!/bin/bash
echo "=== release-workflow-contract.test.mjs ==="
cat tests/unit/release-workflow-contract.test.mjs
echo ""
echo "=== Checking ci.yml for unpinned actions ==="
cat .github/workflows/ci.yml
echo ""
echo "=== Release workflow: softprops action SHA verification ==="
grep -n "softprops\|download-artifact\|upload-artifact\|checkout\|setup-node\|rust-toolchain" .github/workflows/release.ymlLength of output: 3519
One minor pre-existing note (out of scope for this PR): Everything in scope for this PR looks solid. 🐇 ✨ ✅ Actions performedReview triggered.
|
|
Update pushed: What changed:
Validation run locally:
Not run locally:
|
|
Update pushed: Adjusted per the requested packaging-level UAC strategy:
Validation run locally:
Not run locally:
|
|
Updated the desktop Windows verification path after the reported UAC behavior did not reproduce reliably from installed artifacts. Changes in this round:
Validated locally:
@coderabbitai re-review |
🧩 Analysis chain🏁 Script executed: #!/bin/bash
echo "=== src-tauri/app.manifest ==="
cat src-tauri/app.manifest 2>/dev/null || echo "not found"
echo ""
echo "=== src-tauri/build.rs ==="
cat src-tauri/build.rs
echo ""
echo "=== .github/workflows/desktop-build.yml ==="
cat .github/workflows/desktop-build.yml
echo ""
echo "=== tests/unit/desktop-diagnostics-contract.test.mjs ==="
cat tests/unit/desktop-diagnostics-contract.test.mjs
echo ""
echo "=== src-tauri/src/lib.rs (key sections: port cleanup, startup_error, manifest) ==="
# Show full lib.rs
cat src-tauri/src/lib.rs
echo ""
echo "=== tests/unit/run.mjs ==="
cat tests/unit/run.mjsLength of output: 34061
The ✅ Actions performedReview triggered.
|
|
Update pushed: What changed:
Validation performed:
@coderabbitai re-review |
🧩 Analysis chain🏁 Script executed: #!/bin/bash
echo "=== tools/desktop/prepare-tauri-resources.js ==="
cat tools/desktop/prepare-tauri-resources.js
echo ""
echo "=== src-tauri/src/lib.rs (node launcher section) ==="
cat src-tauri/src/lib.rs
echo ""
echo "=== tests/unit/desktop-stage.test.mjs ==="
cat tests/unit/desktop-stage.test.mjs
echo ""
echo "=== tests/unit/desktop-diagnostics-contract.test.mjs ==="
cat tests/unit/desktop-diagnostics-contract.test.mjs
echo ""
echo "=== doc/desktop.md ==="
cat doc/desktop.md
echo ""
echo "=== tests/unit/run.mjs ==="
cat tests/unit/run.mjsLength of output: 48779
One inherent architectural note (not a blocker): Everything in scope is solid. 🐇 ✨ ✅ Actions performedReview triggered.
|
There was a problem hiding this comment.
♻️ Duplicate comments (1)
doc/desktop.md (1)
69-73:⚠️ Potential issue | 🟡 Minor | ⚡ Quick winThe past review comment about documenting both
desktop.logandstartup.logremains unresolved.The previous review flagged that backend stdout/stderr are routed to
startup.logwhen console logging is off, but the documentation still only mentionsdesktop.logat line 72. Line 69 should clarify that backend stdio goes to a different file (startup.log), and the heading at line 75 should specify it controls onlydesktop.loglocation. This mismatch could misdirect users during troubleshooting.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@doc/desktop.md` around lines 69 - 73, Update the documentation to clearly state two log files: explain that when the console/parent terminal is attached backend stdout/stderr are inherited by the terminal and desktop writes local file logs to desktop.log, but when console logging is disabled the backend stdout/stderr are appended to a separate startup.log (not desktop.log); also update the nearby heading that currently references desktop.log so it explicitly says it controls only the desktop.log location and does not cover startup.log, and mention both filenames (desktop.log and startup.log) where relevant.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Duplicate comments:
In `@doc/desktop.md`:
- Around line 69-73: Update the documentation to clearly state two log files:
explain that when the console/parent terminal is attached backend stdout/stderr
are inherited by the terminal and desktop writes local file logs to desktop.log,
but when console logging is disabled the backend stdout/stderr are appended to a
separate startup.log (not desktop.log); also update the nearby heading that
currently references desktop.log so it explicitly says it controls only the
desktop.log location and does not cover startup.log, and mention both filenames
(desktop.log and startup.log) where relevant.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: 2b53d913-09e3-4606-98a8-451bc206eff6
📒 Files selected for processing (5)
doc/desktop.mdsrc-tauri/src/lib.rstests/unit/desktop-diagnostics-contract.test.mjstests/unit/desktop-stage.test.mjstools/desktop/prepare-tauri-resources.js
🚧 Files skipped from review as they are similar to previous changes (4)
- tests/unit/desktop-diagnostics-contract.test.mjs
- tests/unit/desktop-stage.test.mjs
- tools/desktop/prepare-tauri-resources.js
- src-tauri/src/lib.rs
📜 Review details
🔇 Additional comments (4)
doc/desktop.md (4)
12-12: LGTM!
29-29: LGTM!
33-33: LGTM!
52-52: LGTM!
|
Hi @awsl233777 👋 I resolved the merge conflicts with What was resolved
case 'run': await cmdStart(parseStartOptions(args.slice(1))); break;
"devDependencies": {
"@tauri-apps/cli": "^2.11.2",
"@vue/compiler-dom": "^3.5.30",
"opencc-js": "^1.3.1",
"vitepress": "^1.6.4"
}
# after "Pack standalone tarball" step:
- name: Download desktop release assets
uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093
with:
pattern: codexmate-desktop-*
path: desktop-release-assets
merge-multiple: true
- name: Generate release notes from actual commit range
# ... (keep upstream's step as-is)
- name: Create GitHub Release
uses: softprops/action-gh-release@v2
with:
files: |
...
desktop-release-assets/**/*.dmg
desktop-release-assets/**/*.msi
desktop-release-assets/**/*.exe
generate_release_notes: falseCherry-pick commit: |
|
Resolved the What changed:
Local validation run:
Remote status at push time:
@coderabbitai review |
|
✅ Action performedReview finished.
|
|
Update pushed: What changed:
Validation run locally:
Not run locally:
@coderabbitai review |
🧩 Analysis chain🏁 Script executed: #!/bin/bash
echo "=== src-tauri/src/lib.rs (startup/port-check flow) ==="
cat src-tauri/src/lib.rs
echo ""
echo "=== tests/unit/desktop-diagnostics-contract.test.mjs ==="
cat tests/unit/desktop-diagnostics-contract.test.mjs
echo ""
echo "=== tests/unit/run.mjs ==="
cat tests/unit/run.mjsLength of output: 32947
Everything looks solid. 🐇 ✨ ✅ Action performedReview finished.
|
|
Updated this branch with an additional desktop startup guard for the Windows "port 3737 occupied" path. Changes:
Validation run locally:
Limitation:
@coderabbitai review current head again, especially the Windows desktop startup path where an occupied-but-slow backend should become reusable instead of surfacing a false port-occupied failure. |
🧩 Analysis chain🏁 Script executed: #!/bin/bash
echo "=== src-tauri/src/lib.rs ==="
cat src-tauri/src/lib.rs
echo ""
echo "=== tests/unit/desktop-diagnostics-contract.test.mjs ==="
cat tests/unit/desktop-diagnostics-contract.test.mjs
echo ""
echo "=== tests/unit/run.mjs ==="
cat tests/unit/run.mjsLength of output: 34025
Worst-case timing for occupied-but-slow path (before surfacing the error or spawning a fresh backend): The decision tree cleanly handles all four Windows startup scenarios: healthy existing backend (fast reuse), slow-starting backend (grace wait), stale managed backend (cleanup + reuse/respawn), and blocked unmanaged port (user guidance). 🐇 ✨ ✅ Action performedReview finished.
|
|
Follow-up after pushing Remote validation:
New Windows artifact:
Remaining merge gate:
|
|
Updated the desktop startup handling again after the Windows package still reported:
Changes in
Validation run locally:
Artifact inspection:
Limitation:
@coderabbitai review current head again, especially whether the startup error path safely includes enough backend stderr/log context without masking the original failure. |
🧩 Analysis chain🏁 Script executed: #!/bin/bash
echo "=== src-tauri/src/lib.rs ==="
cat src-tauri/src/lib.rs
echo ""
echo "=== tests/unit/desktop-diagnostics-contract.test.mjs ==="
cat tests/unit/desktop-diagnostics-contract.test.mjs
echo ""
echo "=== tests/unit/run.mjs ==="
cat tests/unit/run.mjsLength of output: 36329
The implementation looks solid. 🐇 ✨ ✅ Action performedReview finished.
|
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@src-tauri/src/lib.rs`:
- Around line 177-187: The startup log excerpt helper currently reads the entire
file before trimming it, which can hurt startup-failure handling on large logs.
Update backend_startup_log_excerpt to avoid fs::read on startup.log and instead
open the file, seek near the end, and read only the last 4 KiB before building
the excerpt. Keep the existing unreadable/empty handling and preserve the
current log_path-based messages.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: 770b7238-0b10-4fd8-951b-69c01076da58
📒 Files selected for processing (2)
src-tauri/src/lib.rstests/unit/desktop-diagnostics-contract.test.mjs
🚧 Files skipped from review as they are similar to previous changes (1)
- tests/unit/desktop-diagnostics-contract.test.mjs
📜 Review details
⏰ Context from checks skipped due to timeout. (2)
- GitHub Check: macOS
- GitHub Check: Windows
🔇 Additional comments (1)
src-tauri/src/lib.rs (1)
188-202: LGTM!Also applies to: 314-346, 668-672
| fn backend_startup_log_excerpt() -> String { | ||
| let log_path = backend_startup_log_file_path(); | ||
| let Ok(bytes) = fs::read(&log_path) else { | ||
| return format!("startup.log not readable at {}", log_path.display()); | ||
| }; | ||
| if bytes.is_empty() { | ||
| return format!("startup.log is empty at {}", log_path.display()); | ||
| } | ||
|
|
||
| let keep_from = bytes.len().saturating_sub(4096); | ||
| let text = String::from_utf8_lossy(&bytes[keep_from..]); |
There was a problem hiding this comment.
🩺 Stability & Availability | 🟠 Major | ⚡ Quick win
Tail startup.log without loading the whole file.
fs::read(&log_path) loads the full append-style startup log just to keep 4 KiB. A large accumulated log can stall or OOM startup-failure handling; seek near the end before reading.
Proposed fix
fn backend_startup_log_excerpt() -> String {
let log_path = backend_startup_log_file_path();
- let Ok(bytes) = fs::read(&log_path) else {
+ let Ok(mut file) = fs::File::open(&log_path) else {
return format!("startup.log not readable at {}", log_path.display());
};
+
+ let len = file.metadata().map(|metadata| metadata.len()).unwrap_or(0);
+ let keep_from = len.saturating_sub(4096);
+ if let Err(err) = std::io::Seek::seek(&mut file, std::io::SeekFrom::Start(keep_from)) {
+ return format!("startup.log not seekable at {}: {err}", log_path.display());
+ }
+
+ let mut bytes = Vec::new();
+ if let Err(err) = std::io::Read::read_to_end(&mut file, &mut bytes) {
+ return format!("startup.log not readable at {}: {err}", log_path.display());
+ }
if bytes.is_empty() {
return format!("startup.log is empty at {}", log_path.display());
}
- let keep_from = bytes.len().saturating_sub(4096);
- let text = String::from_utf8_lossy(&bytes[keep_from..]);
+ let text = String::from_utf8_lossy(&bytes);📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| fn backend_startup_log_excerpt() -> String { | |
| let log_path = backend_startup_log_file_path(); | |
| let Ok(bytes) = fs::read(&log_path) else { | |
| return format!("startup.log not readable at {}", log_path.display()); | |
| }; | |
| if bytes.is_empty() { | |
| return format!("startup.log is empty at {}", log_path.display()); | |
| } | |
| let keep_from = bytes.len().saturating_sub(4096); | |
| let text = String::from_utf8_lossy(&bytes[keep_from..]); | |
| fn backend_startup_log_excerpt() -> String { | |
| let log_path = backend_startup_log_file_path(); | |
| let Ok(mut file) = fs::File::open(&log_path) else { | |
| return format!("startup.log not readable at {}", log_path.display()); | |
| }; | |
| let len = file.metadata().map(|metadata| metadata.len()).unwrap_or(0); | |
| let keep_from = len.saturating_sub(4096); | |
| if let Err(err) = std::io::Seek::seek(&mut file, std::io::SeekFrom::Start(keep_from)) { | |
| return format!("startup.log not seekable at {}: {err}", log_path.display()); | |
| } | |
| let mut bytes = Vec::new(); | |
| if let Err(err) = std::io::Read::read_to_end(&mut file, &mut bytes) { | |
| return format!("startup.log not readable at {}: {err}", log_path.display()); | |
| } | |
| if bytes.is_empty() { | |
| return format!("startup.log is empty at {}", log_path.display()); | |
| } | |
| let text = String::from_utf8_lossy(&bytes); |
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@src-tauri/src/lib.rs` around lines 177 - 187, The startup log excerpt helper
currently reads the entire file before trimming it, which can hurt
startup-failure handling on large logs. Update backend_startup_log_excerpt to
avoid fs::read on startup.log and instead open the file, seek near the end, and
read only the last 4 KiB before building the excerpt. Keep the existing
unreadable/empty handling and preserve the current log_path-based messages.
|
Follow-up after pushing Remote validation:
New Windows artifact:
Remaining merge gate:
|
Summary
.dmg,.msi,.exe) alongside existing npm/standalone archivescodexmate analytics exportand theexport-sessions-usageAPI actionValidation
npm run test:unit—All 535 tests passed.node --check cli.jsnode cli.js analytics export --format csv --from 2100-01-01 --to 2100-01-02 --output -node cli.js analytics export --format json --from 2100-01-01 --to 2100-01-02 --output -git diff --checkNotes
webkit2gtk-4.1,rsvg2). Windows/macOS bundle validation runs through GitHub Actions.workflow_dispatch, so the PR validates its release asset handoff by workflow contract tests and review; a real Release asset upload requires running the release workflow for a tag.Closes #169
Closes #139
Summary by CodeRabbit
New Features
Documentation
Bug Fixes
Tests
Chores